use std::fs;

use regex::Regex;

use serde_json::{Value, json};
use tree_sitter::{Node, Parser, TreeCursor};
use walkdir::WalkDir;

pub fn get_package_name(node_cursor: &mut TreeCursor, source_code: &str) -> Option<String> {
    loop {
        let current_node = node_cursor.node();
        if current_node.kind() == "package" {
            // 移动到兄弟节点
            if node_cursor.goto_next_sibling() {
                let scoped_identifier_node = node_cursor.node();
                if scoped_identifier_node.kind() == "scoped_identifier" {
                    let scoped_identifier = &source_code
                        [scoped_identifier_node.start_byte()..scoped_identifier_node.end_byte()];
                    return Some(scoped_identifier.to_string());
                }
            }

            // 一个文件只有一个packgeName
            return None;
        }

        if node_cursor.goto_first_child() {
            continue;
        }

        loop {
            if node_cursor.goto_next_sibling() {
                break;
            }

            if !node_cursor.goto_parent() {
                return None;
            }
        }
    }
}

pub fn get_import(node_cursor: &mut TreeCursor, source_code: &str) -> Vec<String> {
    let mut imports: Vec<String> = vec![];
    loop {
        let current_node = node_cursor.node();
        if current_node.kind() == "import_declaration" {
            imports
                .push(source_code[current_node.start_byte()..current_node.end_byte()].to_string());
        }

        if node_cursor.goto_first_child() {
            continue;
        }

        loop {
            if node_cursor.goto_next_sibling() {
                break;
            }

            if !node_cursor.goto_parent() {
                return imports;
            }
        }
    }
}

pub fn get_url_and_class(
    url_prefix: &str,
    method_prefix: &str,
    node: &Node,
    source_code: &str,
) -> Vec<(String, String, String)> {
    let mut request_mapping_url: Option<String> = None;
    let mut class_name: Option<String> = None;

    // 当前执行过的 @*Mapping
    let mut methd_mapping_method_op: Option<String> = None;
    let mut methd_mapping_op: Option<String> = None;

    // 返回值 <method, url, class>
    let mut result: Vec<(String, String, String)> = vec![];

    let mut cursor = node.walk();
    loop {
        let current_node = cursor.node();
        if current_node.kind() == "annotation" {
            // 查找RequestMapping
            let has_request_mapping =
                by_node_type("identifier", &mut current_node.walk(), source_code)
                    .iter()
                    .any(|item| item == "RequestMapping");
            if has_request_mapping {
                let request_mapping =
                    source_code[current_node.start_byte()..current_node.end_byte()].to_string();
                let re = Regex::new("RequestMapping\\([^\"]*\"([^\"]*)\"\\)").unwrap();
                if let Some(caps) = re.captures(&request_mapping) {
                    request_mapping_url = Some(
                        caps.get(1)
                            .map_or("".to_string(), |m| m.as_str().to_string())
                            .trim_start_matches("/")
                            .trim_end_matches("/")
                            .to_string(),
                    );
                }
                // 逃过当前 annotation 节点
                cursor.goto_next_sibling();
                continue;
            }
        }
        if current_node.kind() == "class" {
            cursor.goto_next_sibling();
            let class_node = cursor.node();
            class_name =
                Some(source_code[class_node.start_byte()..class_node.end_byte()].to_string());
        }
        if current_node.kind() == "class_body" {
            if let Some(request_mapping_url_content) = &request_mapping_url {
                if let Some(class_name_content) = &class_name {
                    // 查询子node
                    let child_result: Vec<(String, String, String)> = get_url_and_class(
                        request_mapping_url_content.as_str(),
                        format!("{class_name_content}#").as_str(),
                        &current_node,
                        source_code,
                    );

                    for result_item in child_result {
                        result.push((
                            format!("{}", result_item.0),
                            format!("{}/{}", url_prefix, result_item.1),
                            format!("{}{}", method_prefix, result_item.2),
                        ));
                    }

                    request_mapping_url = None;
                    class_name = None;

                    // 跳过当前node
                    loop {
                        if cursor.goto_next_sibling() {
                            break;
                        }

                        if !cursor.goto_parent() {
                            return result;
                        }
                    }
                    continue;
                }
            }
        }

        // 查找本node下的GetMapping等，此时method mapping一定为None
        if methd_mapping_op.is_none() && current_node.kind() == "annotation" {
            let request_mapping =
                source_code[current_node.start_byte()..current_node.end_byte()].to_string();
            let re = Regex::new("@(.*)Mapping\\([^\"]*\"([^\"]*)\"\\)").unwrap();
            if let Some(caps) = re.captures(&request_mapping) {
                methd_mapping_method_op = Some(
                    caps.get(1)
                        .map_or("".to_string(), |m| m.as_str().to_string())
                        .to_string(),
                );
                methd_mapping_op = Some(
                    caps.get(2)
                        .map_or("".to_string(), |m| m.as_str().to_string())
                        .trim_start_matches("/")
                        .to_string(),
                );

                // 跳到下一个非annotation节点
                loop {
                    let now_node_node = cursor.node();
                    if now_node_node.kind() != "annotation" {
                        break;
                    }
                    cursor.goto_next_sibling();
                }
                continue;
            }
        }

        if current_node.kind() == "identifier" {
            if let Some(methd_mapping_url) = methd_mapping_op {
                let method_name =
                    source_code[current_node.start_byte()..current_node.end_byte()].to_string();
                // 找到method url
                result.push((
                    methd_mapping_method_op.unwrap_or("".to_string()),
                    format!("{}/{}", url_prefix, methd_mapping_url),
                    format!("{}{}", method_prefix, method_name),
                ));

                // mapping置空
                methd_mapping_method_op = None;
                methd_mapping_op = None;
            }
        }

        if cursor.goto_first_child() {
            continue;
        }

        loop {
            if cursor.goto_next_sibling() {
                break;
            }

            if !cursor.goto_parent() {
                return result;
            }
        }
    }
}

// 获取一个项目的所有接口
pub fn get_url_and_class_from_project(project_path: &str) -> Vec<(String, String, String)> {
    // java 解析器
    let mut parser = Parser::new();
    parser
        .set_language(&tree_sitter_java::LANGUAGE.into())
        .expect("tree_sitter_sequel init fail");

    let result: Vec<(String, String, String)> = WalkDir::new(project_path)
        .sort_by_file_name()
        .follow_links(true)
        .into_iter()
        .flat_map(|entry| {
            if let Ok(path) = entry {
                let full_path: String = path.path().display().to_string();
                if full_path.ends_with(".java") {
                    if let Ok(file_content) = fs::read_to_string(&full_path) {
                        // 解析
                        let node_tree = parser.parse(file_content.as_str(), None).unwrap();

                        // 获取package name
                        let package_name = get_package_name(&mut node_tree.walk(), &file_content)
                            .unwrap_or("".to_string());

                        let result = get_url_and_class(
                            "",
                            format!("{package_name}.").as_str(),
                            &node_tree.root_node(),
                            &file_content,
                        );

                        return result;
                    }
                }
            }
            return vec![];
        })
        .collect();

    return result;
}

pub fn by_node_type(
    node_type: &str,
    node_cursor: &mut TreeCursor,
    source_code: &str,
) -> Vec<String> {
    let root_node = node_cursor.node();
    let mut result: Vec<String> = vec![];
    loop {
        let current_node = node_cursor.node();
        if current_node.kind() == node_type {
            let content = &source_code[current_node.start_byte()..current_node.end_byte()];
            result.push(content.to_string());
        }

        if node_cursor.goto_first_child() {
            continue;
        }

        loop {
            if node_cursor.goto_next_sibling() {
                break;
            }

            node_cursor.goto_parent();
            if root_node == node_cursor.node() {
                return result;
            }
        }
    }
}

pub fn node_by_type<'a>(node: &Node<'a>, node_type: &str) -> Vec<Node<'a>> {
    let mut cursor = node.walk();
    let mut result: Vec<Node<'a>> = vec![];
    loop {
        let current_node = cursor.node();
        if current_node.kind() == node_type {
            result.push(current_node);
        }

        if cursor.goto_first_child() {
            continue;
        }

        loop {
            if cursor.goto_next_sibling() {
                break;
            }

            cursor.goto_parent();
            if node == &cursor.node() {
                return result;
            }
        }
    }
}

pub fn node_by_type_first<'a>(node: &Node<'a>, node_type: &str) -> Option<Node<'a>> {
    let mut cursor = node.walk();
    loop {
        let current_node = cursor.node();
        if current_node.kind() == node_type {
            return Some(current_node);
        }

        if cursor.goto_first_child() {
            continue;
        }

        loop {
            if cursor.goto_next_sibling() {
                break;
            }

            cursor.goto_parent();
            if node == &cursor.node() {
                return None;
            }
        }
    }
}

// 根据类型筛选节点的子节点
pub fn child_node_by_type<'a>(node: &Node<'a>, node_type: &str) -> Vec<Node<'a>> {
    let mut node_cursor = node.walk();
    let node_list: Vec<Node<'a>> = node
        .children(&mut node_cursor)
        .into_iter()
        .filter(|item| item.kind() == node_type)
        .collect();
    return node_list;
}

// 根据类型筛选节点的子节点
pub fn child_node_by_type_first<'a>(node: &Node<'a>, node_type: &str) -> Option<Node<'a>> {
    let mut node_cursor = node.walk();
    let node_op: Option<Node<'a>> = node
        .children(&mut node_cursor)
        .find(|item| item.kind() == node_type);
    return node_op;
}

pub fn node_by_start_and_end<'a>(node: &Node<'a>, start: usize, end: usize) -> Option<Node<'a>> {
    let mut cursor = node.walk();
    loop {
        let current_node = cursor.node();
        if current_node.start_byte() == start && current_node.end_byte() == end {
            return Some(current_node);
        }

        if cursor.goto_first_child() {
            continue;
        }

        loop {
            if cursor.goto_next_sibling() {
                break;
            }

            cursor.goto_parent();
            if node == &cursor.node() {
                return None;
            }
        }
    }
}

// 构造项目的代码缓存行 (com.x.Class#method, file_path, (17, 45))
pub fn code_cache_line(project_path: &str) -> Vec<(String, String, (usize, usize))> {
    // java 解析器
    let mut parser = Parser::new();
    parser
        .set_language(&tree_sitter_java::LANGUAGE.into())
        .expect("tree_sitter_sequel init fail");

    let result: Vec<(String, String, (usize, usize))> = WalkDir::new(project_path)
        .sort_by_file_name()
        .follow_links(true)
        .into_iter()
        .flat_map(|entry| {
            if let Ok(path) = entry {
                let full_path: String = path.path().display().to_string();
                if full_path.ends_with(".java") {
                    if let Ok(file_content) = fs::read_to_string(path.path()) {
                        let node_tree = parser.parse(&file_content, None).unwrap();
                        let root_node: &Node<'_> = &node_tree.root_node();

                        // 筛选出package
                        if let Some(package_declaration_node) =
                            super::base::node_by_type(&root_node, "package_declaration").get(0)
                        {
                            if let Some(scoped_identifier_node) = super::base::node_by_type(
                                &package_declaration_node,
                                "scoped_identifier",
                            )
                            .get(0)
                            {
                                // package name
                                let package_name = &file_content[scoped_identifier_node.start_byte()
                                    ..scoped_identifier_node.end_byte()];

                                // 筛选出class-node
                                let class_nodes =
                                    super::base::node_by_type(&root_node, "class_declaration");
                                let code_cache_line: Vec<(String, String, (usize, usize))> = class_nodes
                                    .into_iter()
                                    .flat_map(|class_node| {
                                        let mut class_node_cursor = class_node.walk();
                                        let class_name_node_op = class_node
                                            .children(&mut class_node_cursor)
                                            .find(|item| item.kind() == "identifier");

                                        if let Some(class_name_node) = class_name_node_op {
                                            // class name
                                            let class_name = &file_content[class_name_node
                                                .start_byte()
                                                ..class_name_node.end_byte()];
                                            let full_class_name =
                                                format!("{package_name}.{class_name}");

                                            // 查询类下的方法
                                            let method_nodes: Vec<Node<'_>> =
                                                super::base::node_by_type(
                                                    &class_node,
                                                    "method_declaration",
                                                );
                                            let method_name_list: Vec<(String, String, (usize, usize))> = method_nodes
                                                .into_iter()
                                                .filter_map(|method_node| {
                                                    // 检查method节点的方法名是否正确
                                                    // 查找指定method_node
                                                    let mut method_node_cursor = method_node.walk();
                                                    let method_name_node_op = method_node
                                                        .children(&mut method_node_cursor)
                                                        .find(|method_node_itme| {
                                                            method_node_itme.kind() == "identifier"
                                                        });

                                                    // 提取方法名
                                                    if let Some(method_name_node) =
                                                        method_name_node_op
                                                    {
                                                        let now_method_name = &file_content
                                                            [method_name_node.start_byte()
                                                                ..method_name_node.end_byte()];
                                                        return Some((
                                                            format!("{full_class_name}#{now_method_name}").to_string(),
                                                            full_path.to_string(),
                                                            (
                                                                method_node.start_byte(),
                                                                method_node.end_byte(),
                                                            ),
                                                        ));
                                                    }
                                                    return None;
                                                })
                                                .collect::<Vec<(String, String, (usize, usize))>>();

                                            // 构造返回值 (com.x.Class#method, file_path, (17, 45))
                                            let mut result: Vec<(String, String, (usize, usize))> =
                                                vec![];
                                            result.push((
                                                format!("{full_class_name}").to_string(),
                                                full_path.to_string(),
                                                (
                                                    class_node.start_byte(),
                                                    class_node.end_byte(),
                                                ),
                                            ));
                                            result.extend(method_name_list);

                                            return result;
                                        }

                                        return vec![];
                                    })
                                    .collect();

                                return code_cache_line;
                            }
                        }
                    }
                } else {
                    return vec![];
                }
            }
            return vec![];
        })
        .collect();

    return result;
}

// 构造项目的继承关系缓存行 (com.x.interface.Class, com.x.impl.Class)
pub fn implement_cache_line(project_path: &str) -> Vec<(String, String)> {
    // java 解析器
    let mut parser = Parser::new();
    parser
        .set_language(&tree_sitter_java::LANGUAGE.into())
        .expect("tree_sitter_sequel init fail");

    let result: Vec<(String, String)> = WalkDir::new(project_path)
        .sort_by_file_name()
        .follow_links(true)
        .into_iter()
        .flat_map(|entry| {
            if let Ok(path) = entry {
                let full_path: String = path.path().display().to_string();
                if full_path.ends_with(".java") {
                    if let Ok(file_content) = fs::read_to_string(&full_path) {
                        // 解析
                        let node_tree = parser.parse(file_content.as_str(), None).unwrap();
                        let root_node = &node_tree.root_node();
                        if let Some(package_declaration_node) =
                            super::base::node_by_type_first(root_node, "package_declaration")
                        {
                            if let Some(scoped_identifier_node) = super::base::node_by_type_first(
                                &package_declaration_node,
                                "scoped_identifier",
                            ) {
                                // package name
                                let package_name = &file_content[scoped_identifier_node.start_byte()
                                    ..scoped_identifier_node.end_byte()];

                                // imports,只包含class-full名称
                                let imports: Vec<String> =
                                    super::base::node_by_type(&root_node, "import_declaration")
                                        .iter()
                                        .flat_map(|item_node| {
                                            return super::base::node_by_type(
                                                item_node,
                                                "scoped_identifier",
                                            );
                                        })
                                        .map(|item_node| {
                                            file_content
                                                [item_node.start_byte()..item_node.end_byte()]
                                                .to_string()
                                        })
                                        .collect();

                                // 遍历类
                                let class_nodes =
                                    super::base::node_by_type(&root_node, "class_declaration");
                                let class_and_imterface: Vec<(String, String)> = class_nodes
                                    .iter()
                                    .flat_map(|class_node_item| {
                                        // 提取类名 和 接口名列表
                                        if let Some(class_name_node) =
                                            child_node_by_type_first(class_node_item, "identifier")
                                        {
                                            let class_name = &file_content[class_name_node
                                                .start_byte()
                                                ..class_name_node.end_byte()];

                                            // 接口
                                            if let Some(implement_nodes_super) =
                                                child_node_by_type_first(
                                                    class_node_item,
                                                    "super_interfaces",
                                                )
                                            {
                                                // 实现接口的短名称
                                                let implement_interface_short_nodes: Vec<Node<'_>> =
                                                    child_node_by_type(
                                                        &implement_nodes_super,
                                                        "type_list",
                                                    )
                                                    .iter()
                                                    .flat_map(|item| {
                                                        node_by_type(item, "type_identifier")
                                                    })
                                                    .collect();

                                                let implement_interface_long_names: Vec<String> =
                                                    implement_interface_short_nodes
                                                        .iter()
                                                        .filter_map(|interface_short_node| {
                                                            let interface_short = &file_content
                                                                [interface_short_node.start_byte()
                                                                    ..interface_short_node
                                                                        .end_byte()];
                                                            return imports.iter().find(
                                                                |interface_long| {
                                                                    interface_long
                                                                        .ends_with(&interface_short)
                                                                },
                                                            );
                                                        })
                                                        .map(|item| item.to_string())
                                                        .collect();

                                                return implement_interface_long_names
                                                    .into_iter()
                                                    .map(|item| {
                                                        (
                                                            item,
                                                            format!(
                                                                "{}.{}",
                                                                package_name, class_name
                                                            )
                                                            .to_string(),
                                                        )
                                                    })
                                                    .collect();
                                            }
                                        }
                                        return vec![];
                                    })
                                    .collect();

                                return class_and_imterface;
                            }
                        }
                    }
                } else {
                    return vec![];
                }
            }
            return vec![];
        })
        .collect();

    return result;
}

#[test]
fn test_get_url_and_class() {
    // java 解析器
    let mut parser = Parser::new();
    parser
        .set_language(&tree_sitter_java::LANGUAGE.into())
        .expect("tree_sitter_sequel init fail");

    // 解析
    let source_file = fs::read_to_string("/home/x/company/gxdac/centerServer/src/main/java/com/lingshu/server/moduler/bigscreen/controller/BigScreenController.java").expect("");
    let node_tree = parser.parse(&source_file, None).unwrap();

    // 获取package name
    let package_name =
        get_package_name(&mut node_tree.walk(), &source_file).unwrap_or("".to_string());

    let result = get_url_and_class(
        "",
        format!("{package_name}.").as_str(),
        &node_tree.root_node(),
        &source_file,
    );
    println!("{:?}", result);
}

#[test]
fn test_get_url_and_class_from_project() {
    let result = get_url_and_class_from_project("/home/x/company/国电一期/server");
    for item in result {
        println!("{} {} {}", item.0, item.1, item.2);
    }
}

// 将Tree-sitter节点转换为可序列化的JSON结构
pub fn node_to_json(node: &Node, source_code: &str) -> Value {
    let mut map = serde_json::Map::new();

    // 基础节点信息
    map.insert(
        "type".to_string(),
        serde_json::to_value(node.kind()).unwrap(),
    );
    map.insert(
        "start_position".to_string(),
        serde_json::to_value({
            let pos = node.start_position();
            json!([pos.row, pos.column])
        })
        .unwrap(),
    );
    map.insert(
        "end_position".to_string(),
        serde_json::to_value({
            let pos = node.end_position();
            json!([pos.row, pos.column])
        })
        .unwrap(),
    );

    // 节点包含的源码片段
    let start_byte = node.start_byte();
    let end_byte = node.end_byte();
    let text = &source_code[start_byte..end_byte];
    map.insert("text".to_string(), serde_json::to_value(text).unwrap());

    // 处理子节点
    if node.child_count() > 0 {
        let mut children = Vec::new();
        let mut cursor = node.walk();

        if cursor.goto_first_child() {
            loop {
                let child_node = cursor.node();
                children.push(node_to_json(&child_node, source_code));

                if !cursor.goto_next_sibling() {
                    break;
                }
            }

            // 返回父节点
            cursor.goto_parent();
        }

        map.insert(
            "children".to_string(),
            serde_json::to_value(children).unwrap(),
        );
    }

    serde_json::Value::Object(map)
}

#[test]
fn test_code_cache_line() {
    let r = code_cache_line("/home/x/company/国电一期/server");
    println!("{:#?}", r);
}

#[test]
fn test_implement_cache_line() {
    let r = implement_cache_line("/home/x/company/国电一期/server");
    println!("{:#?}", r);
}
